﻿package
	{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.utils.*;
	
	public class Player extends MovieClip
		{
		var login:String;
		var maxHealth:Number = 1000;
		var health:Number = maxHealth;
		var hpBar:GaugeBar;
		var slot:InventorySlot;
		
		var arrowPressed:Object;
		
		var baseAttributes:Attribute;
		var weapon:Equipment;
		var inventory:Inventory;
		var statsWindow:StatsWindow;
		
		var resist:Number = 0.7;
		var accel:Number = 0.1;
		var maxSpeed:Number = 10;
		var curSpeed:Number = 0;
		var Xspeed:Number = 0;
		var Yspeed:Number = 0;
		var rotateSpeed:Number = 15;
		var clockWise:Boolean;
		var moving:Boolean = false;
		var passive:Boolean = true;
		var destinationAngle:Number;
		var bitField:Number = 0;
		var fireChrono:Number = getTimer();
		
		public function Player(keyHandler:Object)
			{
			statsWindow = new StatsWindow();
			statsWindow.visible = false;
			
			statsWindow.x = 700;
			statsWindow.y = 200;
			slot = new InventorySlot();
			weapon = new Equipment("Walther P99","Standard gun","Handgun", "Weapon", [["DMG",2],["ACC",40],["ROF",-450]]);
			
			inventory = new Inventory(this);
			
			this.baseAttributes = new Attribute([["HP",50],["MP", 10],["STR", 1],["AGL", 1],["INT", 1],["ROF",500]]);
			baseAttributes.addModificator([["DEF",1],["ACC",50],["RES",1], ["SPD", 1], ["LCK",1]]);
			
			var att:Attribute = new Attribute([["HP", 200], ["MP", 25]]);
			
			att.applyModification(this);
			att.removeModification(this);
			
			this.hpBar = new GaugeBar(this.maxHealth);
			this.health = this.maxHealth;
			if (keyHandler != null)
				{
				this.arrowPressed = keyHandler;
				this.passive = false;
				}
			else
				this.arrowPressed = {37:false, 38:false, 39:false, 40:false, 16:false, 77:false, 80:false};
			//this.torso.gotoAndStop(18);
			//var beret:Beret = new Beret();
			//this.head.addChild(beret);
			}
		
		public function stateToBit()
			{
			this.bitField = (arrowPressed[37] && 1) | (arrowPressed[38] && 2);
			this.bitField |= (arrowPressed[39] && 4)|(arrowPressed[40] && 8)|(arrowPressed[16] && 16);
			}
		
		public function bitToState()
			{
			this.arrowPressed[37] = this.bitField & 1;
			this.arrowPressed[38] = this.bitField & 2;
			this.arrowPressed[39] = this.bitField & 4;
			this.arrowPressed[40] = this.bitField & 8;
			this.arrowPressed[16] = this.bitField & 16;
			}
		
		public function normRotat(angle:Number):Number
			{
			return (angle<0)?angle+360:angle;
			}
		
		public function showGUI()
			{
			var hat = new Equipment("Green beret","Military hat","Beret", "Hat", [["DEF",3],["STR",2],["AGL",10]]);
			var cap = new Equipment("Red cap","Baseball cap","Cap", "Hat", [["HP", 9999],["DEF",999],["STR",999],["AGL",999],["LCK",999]]);
			var glove = new Equipment("Leather Gloves","Leather Gloves","Gloves", "Gloves", [["DEF",5],["STR",8],["LCK",13]]);
			var pads = new Equipment("Iron pads","Iron pads","ShoulderPads", "Shoulders", [["DEF",12]]);
			
			parent.addChildAt(cap,0);
			parent.addChildAt(pads,0);
			pads.x = 200+Math.random()*200;
			pads.y = 200+Math.random()*200;
			
			parent.addChildAt(glove,0);
			glove.x = 200+Math.random()*200;
			glove.y = 200+Math.random()*200;
			
			parent.addChildAt(hat,0);
			hat.x = 200+Math.random()*200;
			hat.y = 200+Math.random()*200;
			
			parent.addChildAt(this.weapon,0);
			
			stage.addChild(this.hpBar);
			//stage.addChild(this.slot);
			stage.addChild(this.inventory);
			stage.addChild(this.statsWindow);
			slot.x = 50;
			slot.y = 80;
			}
		
		public function addEvents()
			{
			this.addEventListener(Event.ENTER_FRAME, run);
			}
		
		public function takeDamage(damage:Number)
			{
			var damageRate:Number = damage/this.maxHealth;
			this.health -= damage;
			if (this.health < 0) this.health = maxHealth;
			this.hpBar.refreshGauge(this.health/this.maxHealth);
			
			var blood:Blood = new Blood();
			parent.addChildAt(blood, 1);
			var r1 = signedRand(damageRate*10);
			blood.x = this.x + signedRand(50);
			blood.y = this.y + signedRand(50);
			blood.scaleX = 1+r1;
			blood.scaleY = 1+r1;
			blood.rotation = Math.random()*3600;
			hpBar.nbchild.text= String(this.health);
			}
		
		public function run(e:Event)
			{
			if (this.passive)
				{
				bitToState();
				doRotation(this.destinationAngle);
				}
			else
				doRotation(computeAngle());
			
			computeMove();
			
			if (arrowPressed[16] && (getTimer()-fireChrono > this.baseAttributes.getStat("ROF")))
				{
				fireChrono = getTimer();
				fireWeapon();
				}
			if (arrowPressed["s"])
				{
				getStats();
				}
			if (arrowPressed[17])
				{
				grabItem();
				}
			if (arrowPressed["i"])
				{
				inventory.visible = !inventory.visible;
				}
				
			}
		
		public function grabItem()
			{
			for (var i=0; i< parent.numChildren; i++)
				{
				var item = this.parent.getChildAt(i);
				if (item is Equipment && this.hitTestObject(item))
					{
					inventory.pickUpItem(item);
					parent.removeChild(item);
					item.equip(this);
					break;
					}
				}
			}
		
		public function getStats(display:Boolean=true)
			{
			statsWindow.stats.text = this.baseAttributes.formatAttributes();
			if (display) statsWindow.visible = !statsWindow.visible;
			}
		
		public static function signedRand(coef:Number):Number
			{
			var sign:Number = Math.random();
			sign = (sign>0.5)?1:-1;
			var rand:Number = Math.random() * coef * sign;
			return rand;
			}
		
		public function fireWeapon()
			{
			if (weapon)
				weapon.play();
			else
				return;
			this.torso.play();
			
			var gun:Point = new Point(weapon.x, weapon.y);
			
			gun = this.torso.rightHand.localToGlobal(gun);
			gun = parent.globalToLocal(gun);
			
			var shot:Projectile = new Projectile();
			parent.addChildAt(shot, parent.getChildIndex(this));
			shot.hitArea = Sprite(shot.hit);
			var acc:int = ((100-this.baseAttributes.getStat("ACC"))/200)*180;
			shot.rotation = this.torso.rotation + signedRand(acc);
			shot.x = gun.x;
			shot.y = gun.y;
			shot.setAngle();
			shot.addEvent();
			
			var bullet:EmptyRound = new EmptyRound();
			parent.addChildAt(bullet, parent.getChildIndex(this));
			bullet.x = gun.x;
			bullet.y = gun.y;
			var rand:Number = Math.random()*Math.random();
			bullet.scaleX += rand;
			bullet.scaleY += rand;
			bullet.rotation = this.torso.rotation+signedRand(30);
			}
		
		public function computeMove()
			{
			var hor:Boolean = arrowPressed[37] || arrowPressed[39];
			var ver:Boolean = arrowPressed[38] || arrowPressed[40];
			moving = hor || ver;
			
			if (moving)
				{
				if (this.legs.currentFrame==1)
					this.legs.gotoAndPlay(5);
				if (curSpeed < maxSpeed)
					curSpeed += maxSpeed * accel;
				else
					curSpeed = maxSpeed;
				}
			else
				{
				this.legs.gotoAndStop(1);
				if (curSpeed > 2)
					curSpeed *= resist;
				else
					curSpeed = 0;
				}
			
			if (arrowPressed[39]) Xspeed = curSpeed;
			else if (arrowPressed[37]) Xspeed = -curSpeed;
			if (arrowPressed[40]) Yspeed = curSpeed;
			else if (arrowPressed[38]) Yspeed = -curSpeed;
			
			this.x += Xspeed;
			this.y += Yspeed;
			
			if (!this.passive)
				{
				parent.x -= Xspeed*parent.scaleX;
				parent.y -= Yspeed*parent.scaleY;
				}
			
			if (!hor)
				{
				if (Math.abs(Xspeed) > 2) Xspeed *= resist;
				else Xspeed = 0;
				}
			if (!ver)
				{
				if (Math.abs(Yspeed) > 2) Yspeed *= resist;
				else Yspeed= 0;
				}
			}
			
		public function computeAngle():Number
			{
			var oppose:Number = (parent.mouseY-this.y);
			var adjacent:Number = (parent.mouseX-this.x);
			var angle:Number = Math.atan(oppose/adjacent)*MainClass.toDegree;
			
			if (adjacent <0)
				angle += 90;
			else
				angle -= 90;
			
			return angle;
			}
		
		public function doRotation(destAngle:Number)
			{
			destAngle = normRotat(destAngle);
			
			var sens:Number = 1;
			var rotation360:Number = normRotat(this.torso.rotation);
			var difference:Number = destAngle - rotation360;
			this.clockWise = ((difference >= 0 || difference < -180) && difference <= 180 );
			
			if (!clockWise) sens = -1;
			
			if (Math.abs(difference) > rotateSpeed)
				{
				this.head.rotation += rotateSpeed*sens;
				this.torso.rotation += rotateSpeed*sens;
				}
			else
				{
				this.head.rotation = destAngle;
				this.torso.rotation = destAngle;
				}
			if (Math.abs(this.legs.rotation - this.torso.rotation) > 50)
				this.legs.rotation = rotation360;
			}
		}
	}
